/***************************************************************************
 创建者: 华磊
 开始时间: 2018.9.26
 copyright: (C) 华友高新
 修改说明: (每次有修改就添加一条，带有 修改人，修改时间，修改描述)
 example (1) 李文友 2017.5.8 类的具体实现代码编写

 ***************************************************************************
 *  @file linematch.h
 *  功能: 直线探测功能
 *
 *                                                                         *
 ***************************************************************************/
#ifndef LINEMATCH_H
#define LINEMATCH_H
#include <qstring.h>
#include "opencv2/core/core.hpp"
#include "opencv2/nonfree/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/legacy/legacy.hpp"
#include <QMutex>

using namespace cv;

class LineMatch
{
public:
    LineMatch();

public:
    int showDebugWindow(int id,const Mat &imageIn);
    int setLineDetectPara(double rhoIn, double thetaIn, int thresholdIn,
                      double minLineLengthIn, double maxLineGapIn);
    int detectLine(QString filePath);
    /**
     * @brief detectVMark_mapFile
     * @param filePath
     * @param min_angle unit is rad
     * @param max_angle unit is rad
     * @param max_distance 交点离直线端点的最大距离 pix
     * @param allow_vDistance　多个vmark之间的距离 pix
     * @param allow_vAngle　多个vmark之间的角度 rad
     * @param x_out　ｖmark　的交点
     * @param y_out　ｖmark　的交点
     * @param r_out　ｖmark　的角度
     * @return
     */
    int detectVMark_mapFile(QString filePath, double min_angle, double max_angle, double max_distance, double allow_vDistance, double allow_vAngle,
                            vector<double> &x_out, vector<double> &y_out, vector<double> &r_out);
    /**
     * @brief detectVMark_mat
     * @param imageIn
     * @param min_angle unit is rad
     * @param max_angle unit is rad
     * @param max_distance 交点离直线端点的最大距离 pix
     * @param allow_vDistance　多个vmark之间的距离 pix
     * @param allow_vAngle　多个vmark之间的角度 rad
     * @param x_out　ｖmark　的交点 pix
     * @param y_out　ｖmark　的交点 pix
     * @param r_out　ｖmark　的角度 unit is rad
     * @return
     */
    int detectVMark_mat(const Mat &imageIn, double min_angle, double max_angle, double max_distance, double allow_vDistance, double allow_vAngle,
                            vector<double> &x_out, vector<double> &y_out, vector<double> &r_out);

private:
    bool getCrossPoint(Vec4i firstLine, Vec4i secondLine,Point2f &crossPoint,
                                  double &crossDistance1,double &crossDistance2,double &angle_a, double &angle_b);
    bool getCrossPoint_double(vector<double> firstLine, vector<double> secondLine,Point2f &crossPoint,
                                  double &crossDistance1,double &crossDistance2,double &angle_a, double &angle_b);
    int processPicture(const Mat &originPicture,Mat &transformedPicture);
    int detectLine(const Mat &imagineSource, vector<Vec4i> &linesOut);
    int detectVMark(const vector<Vec4i> &linesIn, double min_angle, double max_angle, double max_distance,
                    vector<double> &x_out, vector<double> &y_out, vector<double> &r_out);
    bool isVMark(Vec4i firstLine, Vec4i secondLine, double min_angle, double max_angle,
                            double max_distance, double &x_out,double &y_out, double &r_out);
    int displayVMark(const Mat &originPicture,vector<double> &x_out, vector<double> &y_out, vector<double> &r_out);

    int displayLine(const Mat &originPicture,vector<Vec4i> &linesIn);

    int deleteTheSameVMark(double allowDistance,double allowAngle,
                           vector<double> &x_out, vector<double> &y_out, vector<double> &r_out);
    bool isTheSameVMark(double allowDistance,double allowAngle,double x_1, double y_1, double r_1,
                        double x_2, double y_2, double r_2);

    /**
     * @brief angleRotationJudgement 考虑哪种角度旋转方法最近
     * @param targetAngle
     * @param initialAngle
     * @return
     */
    double angleRotationJudgement(double targetAngle,double initialAngle);


private:
    double rho;
    double theta;
    int threshold_pt;
    double minLineLength;
    double maxLineGap;

    QMutex safeMutex;
    std::vector<Vec4i> detectedLines;
    std::vector<double> x_detected;
    std::vector<double> y_detected;
    std::vector<double> r_detected;
};

#endif // LINEMATCH_H
